package icraf.carbon.gui;

import java.text.DecimalFormat;
import java.text.NumberFormat;

import icraf.carbon.core.AbacusContainer;
import icraf.carbon.core.CostBenefitUnit;
import icraf.carbon.core.LandCover;
import icraf.carbon.core.Project;
import icraf.carbon.core.Zone;
import icraf.carbon.core.Zone.DataType;
import icraf.carbon.gui.model.InstantCounter;

import javax.swing.ListModel;

public class LCZTableModel extends ProjectMatrixTableModel implements InstantCounter<LCZTableModel>{
	private static final long serialVersionUID = 8968868974903218229L;
	private Object attributes;
	private DataType dataType;
	private boolean editable = true;
	DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance();
	private boolean isNegativeAllowed = false;
	private LCRowHeaderModel lcRowHeaderModel = new LCRowHeaderModel(this);

	private Project project;

	public LCZTableModel() {
		super();
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		return Double.class;
	}

	@Override
	public int getColumnCount() {
		if (project == null)
			return 0;
		return project.getNumberOfZone();

	}

	@Override
	public String getColumnName(int col) {
		if (project == null)
			return null;
		return project.getZoneList().get(col).getLabel();
	}

	public DataType getDataType() {
		return dataType;
	}


	public AbacusContainer getProject() {
		return project;
	}

	@Override
	public int getRowCount() {
		if (project == null)
			return 0;
		return project.getLandCoverList().size();
	}

	@Override
	public ListModel<Object> getRowHeaderModel() {
		return lcRowHeaderModel;
	}

	@Override
	public Object getValueAt(int row, int column) {
		if (project == null)
			return null;
		Zone z = project.getZoneList().get(column);
		LandCover lc = project.getLandCoverList().get(row);
		double val = Double.NaN;
		if (dataType == DataType.NPV) {
			if (attributes instanceof CostBenefitUnit)
				//val = z.getNPV(lc, (CostBenefitUnit) attributes);
				val = z.getValue(lc, DataType.NPV, (CostBenefitUnit) attributes);

		} else if (dataType == DataType.CARBONSTOCK) {
			Double d = z.getCarbonStockList().get(lc);
			if (d != null)
				val = d.doubleValue();

		}
		return (Double.isNaN(val)) ? null : val;
	}

	@Override
	public boolean isCellEditable(int row, int col) {
		return editable;
	}

	public boolean isEditable() {
		return editable;
	}

	public boolean isNegativeAllowed() {
		return isNegativeAllowed;
	}

	private void setDataType(DataType dataType, Object attributes) {
		this.dataType = dataType;
		this.attributes = attributes;
	}

	public void setEditable(boolean editable) {
		this.editable = editable;
	}

	public void setNegativeAllowed(boolean isNegativeAllowed) {
		this.isNegativeAllowed = isNegativeAllowed;
	}

	public void setProject(Project project, DataType t, Object attributes) {
		this.project = project;
		setDataType(t, attributes);
		fireTableStructureChanged();
		lcRowHeaderModel.setProject(project);
	}

	@Override
	public void setValueAt(Object value, int row, int col) {
		if (value == null)
			return;
		double d = 0;
		if (value instanceof String) {
			String strVal = (String) value;
			strVal = strVal.replaceAll( "[^\\d.,-Ee]", "" );
			try {
				d = formatter.parse(strVal.trim()).doubleValue();
			} catch (Exception e) {
				return;
			}
		} else {
			d = ((Double) value).doubleValue();
		}
		if (!isNegativeAllowed) {
			d = Math.abs(d);
		}
		Zone z = project.getZoneList().get(col);
		LandCover lc = project.getLandCoverList().get(row);
		if (dataType == DataType.NPV) {
			if (attributes instanceof CostBenefitUnit)
				//z.setNPV(d, lc, (CostBenefitUnit) attributes);
				z.setValue(d, lc, DataType.NPV, (CostBenefitUnit) attributes);
		} else if (dataType == DataType.CARBONSTOCK) {
			z.getCarbonStockList().put(lc, d);
		}
		fireTableCellUpdated(row, col);
	}

	@Override
	public LCZTableModel createInstant() {
		return new LCZTableModel();
	}

}
